package org.goj.practice.service.impl;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jcraft.jsch.JSchException;
import org.goj.common.entity.practice.Duplicate;
import org.goj.common.entity.practice.SourceCode;
import org.goj.common.model.UbuntuEntity;
import org.goj.common.utils.ExecuteShellUtil;
import org.goj.practice.mapper.DuplicateMapper;
import org.goj.practice.service.DuplicateService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.goj.practice.service.SourceCodeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.*;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 相似度检测表 服务实现类
 * </p>
 *
 * @author CK
 * @since 2021-05-12
 */
@Service
public class DuplicateServiceImpl extends ServiceImpl<DuplicateMapper, Duplicate> implements DuplicateService {

    @Autowired
    private UbuntuEntity ubuntuEntity;

    @Resource
    private DuplicateMapper duplicateMapper;

    @Resource
    private SourceCodeService sourceCodeService;

    private String execCmd(String cmd) {
        ExecuteShellUtil executeShellUtil = ExecuteShellUtil.getInstance();
        String result;
        try {
            executeShellUtil.init(ubuntuEntity);
            result = executeShellUtil.execCmd(cmd);
        } catch (Exception e) {
            e.printStackTrace();
            result = "error";
        }
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<Duplicate> detection(List<Integer> solutionIds, Integer language) {
        List<Duplicate> collect = List.of();
        Map<Integer, String> languageMap = Map.of(0, "c", 1, "cpp", 3, "java", 6, "py");
        Map<Integer, String> execMap = Map.of(0, "c/c++", 1, "c/c++", 3, "java19", 6, "python3");
        QueryWrapper<SourceCode> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("solution_id", solutionIds);
        List<SourceCode> sourceCodes = sourceCodeService.list(queryWrapper);
        String path = "/home/judge/duplicate/detection/";
        String path1 = "/home/judge/duplicate/";
        try {
            solutionIds.forEach(t -> execCmd("mkdir -p " + path + "student" + t + "/src/\n" +
                    "touch " + path + "student" + t + "/src/" + "a." + languageMap.get(language) + "\n" +
                    "echo '" + sourceCodes.stream().filter(i -> i.getSolutionId().equals(t)).findFirst().get().getSource()
                    + "' > " + path + "student" + t + "/src/" + "a." + languageMap.get(language)));
            String result = execCmd("java -jar " + path1 + "jplag.jar -r " + path1 + "tmp -s " + path1 + "detection -l " + execMap.get(language) + " | grep Comparing");
            collect = Arrays.stream(result.split("\n")).filter(StrUtil::isNotBlank).map(t -> {
                Duplicate duplicate = new Duplicate();
                duplicate.setSolutionIdOne(Integer.valueOf(t.split("[ ]+")[1].split("-")[0].substring(7)));
                duplicate.setSolutionIdTwo(Integer.valueOf(t.split("[ ]+")[1].split("-")[1].split(":")[0].substring(7)));
                duplicate.setRatio(Double.valueOf(t.split("[ ]+")[2]));
                return duplicate;
            }).collect(Collectors.toList());
            int b = duplicateMapper.saveOrUpdate(collect);
            Assert.isTrue(b > 0, "相似度检测失败");
        } catch (Exception e) {
            e.printStackTrace();
            Assert.isTrue(false, "相似度检测失败,提交代码过于简略");
        } finally {
            execCmd("rm -rf " + path1 + "detection " + path1 + "tmp");
        }
        return collect;
    }

}
